package com.zyy.jomap.resolve;

import com.github.javaparser.JavaParser;
import com.github.javaparser.ParseResult;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.ImportDeclaration;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.VariableDeclarator;
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
import com.zyy.jomap.JoMapProcessor;
import com.zyy.jomap.constant.Constant;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 解析Java文件--OK
 * 使用JavaParser解析变量的类型--source
 */
public class ResolveJavaParser {


    /** 正则匹配 **/
    private static Pattern pattern = Pattern.compile(Constant.JOMAPPER_REG);

    /**  匹配的变量类(原类)和目标类映射列表 key:com.zyy.jomap.bo.User, value:[com.zyy.jomap.bo.UserBO, com.zyy.jomap.bo.UserVO] **/
    private static Map<String, List<String>> varClazzKeyTargetClazzListMap=new HashMap<>();

    public static void main(String[] args) {
        String testClazzAbsPath=ResolveJava.getClazzAbsPath("com.zyy.jomap.back.TestController");
        Map<String,List<String>> map=resolveJava(Arrays.asList(testClazzAbsPath));
        System.out.println(map);
    }

    /***
     * 表达式解析入口
     * @param javaFileAbsPathList
     */
    public static Map<String, List<String>> resolveJava(List<String> javaFileAbsPathList){
        String SRC_PATH=GenerateMapFile.getProjectSrcPath();
        //String SRC_PATH= JoMapProcessor.projectDirAbsPath;
        TypeSolver reflectionType=new ReflectionTypeSolver();
        TypeSolver javaParserType=new JavaParserTypeSolver(new File(SRC_PATH));
        CombinedTypeSolver combinedTypeSolver=new CombinedTypeSolver();
        combinedTypeSolver.add(reflectionType);
        combinedTypeSolver.add(javaParserType);
        JavaSymbolSolver symbolSolver=new JavaSymbolSolver(combinedTypeSolver);
        JavaParser javaParser=new JavaParser();
        javaParser.getParserConfiguration().setSymbolResolver(symbolSolver);
        for(String javaFileAbsPath:javaFileAbsPathList){
            try {
                ParseResult<CompilationUnit> result = javaParser.parse(new File(javaFileAbsPath));
                CompilationUnit cu=result.getResult().get();
                List<MethodDeclaration> methodDeclarationList=cu.findAll(MethodDeclaration.class);
                Map<String,String> typeNameKeyImpoertMap=new HashMap<>();
                NodeList<ImportDeclaration> importList=cu.getImports();
                for(ImportDeclaration importDeclaration:importList){
                    String clazzImport=importDeclaration.getName().toString();
                    int lastDotIndex=clazzImport.lastIndexOf(".");
                    String typeName=clazzImport.substring(lastDotIndex+1,clazzImport.length());
                    typeNameKeyImpoertMap.put(typeName,clazzImport);
                }
//                JoMapProcessor.sPrintMsg("resolve java file...........",javaFileAbsPath);
                for(MethodDeclaration methodDeclaration:methodDeclarationList){
                    List<VariableDeclarator> variableDeclaratorList= methodDeclaration.findAll(VariableDeclarator.class);
                    Map<String,String> varNameKeyClazzPackageMap=new HashMap<>();
                    for(VariableDeclarator variableDeclarator:variableDeclaratorList){
//                        JoMapProcessor.sPrintMsg("resolve field::::::::::",variableDeclarator.getName().toString());
                        try {
                            //当前项目中的类型
                            if(variableDeclarator.getType().resolve().isReferenceType()){
                                String varType=variableDeclarator.getType().resolve().asReferenceType().getQualifiedName();
                                if(varType.indexOf("List")>-1){
                                    varType=variableDeclarator.getType().resolve().asReferenceType().typeParametersValues().get(0).asReferenceType().getQualifiedName();
                                }
                                varNameKeyClazzPackageMap.put(variableDeclarator.getName().toString(),varType);
                            }
                        }catch (Exception e){
                            //三方jar包中的类型
                            String varJarClazzName=variableDeclarator.getType().toString();
                            if(varJarClazzName.startsWith("List<")){
                                //是数组类型时截取数组中的类型名
                                varJarClazzName=varJarClazzName.substring(5,varJarClazzName.length()-1);
                            }
                            String importClazz=typeNameKeyImpoertMap.get(varJarClazzName);
                            varNameKeyClazzPackageMap.put(variableDeclarator.getName().toString(),importClazz);
                        }
                    }
                    String methodBody=methodDeclaration.getBody().toString();
                    Matcher matcher = pattern.matcher(methodBody);
                    //正则解析
                    while(matcher.find()){
//                        JoMapProcessor.sPrintMsg("match group",matcher.group(0));
                        String type=matcher.group(matcher.groupCount());
                        String[] typeArr=type.replace(" ","").split(",");
                        String variableName=typeArr[0];
                        String targetTypeName=typeArr[1].replace(".class","");
                        String varImport=varNameKeyClazzPackageMap.get(variableName);
                        String targetImport=typeNameKeyImpoertMap.get(targetTypeName);
                        if(varImport!=null){
                            if(varImport!=null&&targetImport!=null){
                                if(varClazzKeyTargetClazzListMap.get(varImport)!=null){
                                    varClazzKeyTargetClazzListMap.get(varImport).add(targetImport);
                                }else if(varClazzKeyTargetClazzListMap.get(targetImport)!=null){
                                    varClazzKeyTargetClazzListMap.get(targetImport).add(varImport);
                                }else{
                                    List<String> targetImportList=new ArrayList<>();
                                    targetImportList.add(targetImport);
                                    varClazzKeyTargetClazzListMap.put(varImport,targetImportList);
                                }
                            }
                        }
                    }
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        JoMapProcessor.sPrintMsg("resolve java map: ",varClazzKeyTargetClazzListMap.toString());
        return varClazzKeyTargetClazzListMap;
    }
}
